/**	@file operators.h
 *	@brief Arithmetic operations - constructions of composite expresions. */
#ifndef operators_majdo_
#define operators_majdo_
#include "Ex.h"
namespace sympycpp {
class Expr;
/**	@class Operations 
 *	@brief Basic simplification and construction of expresions by operations. */
class Operations{
public:
	/**	@brief Addition for class Exper.
	 * 	Expr is wrapper class for expressions. This function unpack representation 
	 * 	of expression inside Expr and invoke special functions . */
	static Expr operatorAdd(const Expr &,const Expr &);
	/**	@brief Subtraction for class Expr.
	 * 	Expr is wrapper class for expressions. This function unpack representation 
	 * 	of expression inside Expr and invoke special functions . */
	static Expr operatorSub(const Expr &,const Expr &);
	/**	@brief Multiplication for class Expr.
	 * 	Expr is wrapper class for expressions. This function unpack representation 
	 * 	of expression inside Expr and invoke special functions . */
	static Expr operatorMul(const Expr &,const Expr &);
	/**	@brief Division for class Expr.
	 * 	Expr is wrapper class for expressions. This function unpack representation 
	 * 	of expression inside Expr and invoke special functions . */
	static Expr operatorDiv(const Expr &,const Expr &);
	/**	@brief Power for class Expr.
	 * 	Expr is wrapper class for expressions. This function unpack representation 
	 * 	of expression inside Expr and invoke special functions . */
	static Expr operatorPow(const Expr & L,const Expr & R);
	/**	@brief 	Clever and safe addition.
	 *	Function makes basic simplifications.
	 *	This way of clever construction doesn't modify input expressions. <br/>
	 *	For simplification and construction is using function
	 *	addition(Ex * &, Ex * &, const allocationPolicy), but it works only with copies
	 *	of the input expressions.
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@see addition(Ex * &, Ex * &, const allocationPolicy)
	 *	@param[in] L is left addend
	 *	@param[in] R is right addend
	 *	@return addition <i>L</i> and <i>R</i>  */
	static Ex * addition(const Ex * L, const Ex * R);
	/**	@brief Clever and safe subtraction.
	 * 	This function transform subtraction from A  - B to A + (-B) 
	 * 	and construction is made by addition.
	 *	@see addition(const Ex * , const Ex *) */
	static Ex * subtraction(const Ex * L, const Ex * R);
	/**	@brief Clever addition.
	 *	Function makes basic simplifications.
	 *	Construction of new expression uses memory from input parameters <i>L</i> and <i>R</i>.
	 *	@warning Parameters <i>L</i> and <i>R</i> are deleted and set to null !
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@see addition(const Ex *, const Ex *)
	 *	@see allocationPolicy --> special memory management
	 *	@param[in] L is left addend
	 *	@param[in] R is right addend
	 *	@return addition <i>L</i> and <i>R</i>   */
	static Ex * addition(Ex * & L,Ex * & R,const allocationPolicy);
	/**	@brief Clever and safe subtraction.
	 * 	This function transform subtraction from A  - B to A + (-B) 
 	 * 	and construction is made by addition.
	 *	Construction of new expression uses memory from input parameters <i>L</i> and <i>R</i>.
	 *	@warning Parameters <i>L</i> and <i>R</i> are deleted and set to null !
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@see allocationPolicy --> special memory management
	 *	@see addition(Ex * &, Ex * &,const allocationPolicy) */
	static Ex * subtraction(Ex * & L,Ex * & R,const allocationPolicy);
	/**	@brief 	Clever and safe multiplication.
	 *	This function is clever multiplication. It detects parts of expressions which can be simplified and 
	 *	makes these reduction. 
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@param[in] L is first factor
	 *	@param[in] R is second factor
	 *	@return new expressions xpression
	 *	@see multiplication(Ex * &,Ex * &,const allocationPolicy)  */
	static Ex* multiplication(const Ex * L,const Ex * R);
	/**	@brief 	Clever and safe multiplication.
	 *	This function is clever multiplication. It detects parts of expressions which can be simplified and 
	 *	makes these reduction. 
	 *	Construction of new expression uses memory from input parameters <i>L</i> and <i>R</i>.
	 *	@warning Parameters <i>L</i> and <i>R</i> are deleted and set to null !
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@param[in] L is first factor
	 *	@param[in] R is second factor
	 *	@return new expressions xpression
	 *	@see allocationPolicy --> special memory management
	 *	@see multiplication(const Ex *,const Ex *)  */
	static Ex* multiplication(Ex* & L,Ex* & R,const allocationPolicy);
	/**	@brief 	Clever and safe exponentiation.
	 *	Function makes basic simplification as powers of zero are always zero, 
	 *	powers of one are one etc.
	 *	This way of clever construction doesn't modify input expressions. <br/>
	 *	For simplification and construction is using function
	 *	power(Ex * &, Ex * &, const allocationPolicy), but it works only with copies
	 *	of the input expressions.
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@see power(Ex * &, Ex * &, const allocationPolicy)
	 *	@param[in] base is base of the power
	 *	@param[in] exponent is exponent of the power
	 *	@return base to the power of exponent */
	static Ex * power(const Ex * base, const Ex * exponent);
	/**	@brief Clever and safe  division.
	 **	This function is clever division. It detects parts of expressions which can be simplified and 
	 *	makes these reduction. 
	 *	Sympy-cpp does not contain class that represents divisions. The division is represented 
	 *	by classes Mul and Pow and consequently this function uses functions for multiplications and powers. 
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@param[in] numerator is numerator
	 *	@param[in] denominator is denominator
	 *	@return new expressions xpression
	 *	@see power(const Ex *, const Ex *)
	 *	@see multiplication(const Ex *,const Ex *)  */
	static Ex * division(const Ex * numerator, const Ex * denominator);
	/**	@brief  Clever exponetiation.
	 *	Function makes basic simplification like powers of zero are always zero, 
	 *	powers of one are one etc.<br/>
	 *	Construction of new expression uses memory from input parameters <i>base</i> and <i>exponent</i>.
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@warning Parameters <i>base</i> and <i>exponent</i> are deleted and set to null !
	 *	@see power(const Ex *, const Ex *)
	 *	@see allocationPolicy --> special memory management
	 *	@param[in] base is base of the power
	 *	@param[in] exponent is exponent of the power
	 *	@return base to the power of exponent */
	static Ex * power(Ex * & base, Ex * & exponent, const allocationPolicy);
	/**	@brief Clever and safe  division.
	 *	This function is clever division. It detects parts of expressions which can be simplified and 
	 *	makes these reduction. 
	 *	Sympy-cpp does not contain class that represents divisions. The division is represented 
	 *	by classes Mul and Pow and consequently this function uses functions for multiplications and powers. 
	 *	@warning The function returns new alocated memory, that has to be deleted by users.
	 *	@warning Parameters <i>denominator</i> and <i>numerator</i> are deleted and set to null !
	 *	@param[in] numerator is numerator
	 *	@param[in] denominator is denominator
	 *	@return new expressions xpression
	 *	@see allocationPolicy --> special memory management
	 *	@see power(Ex * &, Ex * &, const allocationPolicy)
	 *	@see multiplication(Ex * &,Ex * &,const allocationPolicy)  */
	static Ex * division(Ex * & numerator, Ex * & denominator, const allocationPolicy);
private:
	Operations() {}
	Operations(const Operations &) {}
	/** @brief Secondary function for better readability of code (very  short & simple). */ 
	static inline Ex* releaseBothReturnFirst(Ex * & first, Ex * & second);
	///	@brief Multiplication for two multiple expressions.
	static Ex* multiplicationMultiples(Ex* &,Ex* &,const allocationPolicy);
	///	@brief Multiplication for a multiple expression and another expression.
	///	@warning First multiplicad has to be multiple and second can't be multiple.
	///	@see multiplicationMultiples() for two multiples
	static Ex* multiplicationOneMultiple(Ex* &,Ex* &,const allocationPolicy);
	///	@brief Multiplication for a number and another expression.
	///	@warning First multiplicand has to be number and second can't be number or multiple.
	///	@see multiplicationOneMultiple() or multiplicationMultiples()
	static Ex* multiplicationOneNumber(Ex* &,Ex* &,const allocationPolicy);
};
}
#endif
